﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.Diagnostics;
using HisoftSmart.Client.AutomationClient.UIAutomationServiceReference;
using System.Text;
using HisoftSmart.Client.AutomationClient.Actions;
using Microsoft.Phone.Info;

namespace HisoftSmart.Client.AutomationClient
{
    public class AutomationClient :IDisposable
    {
        private const int GetNextActionTimeoutInMilliseconds = 1000;
        private const int ErrorSleepTimeoutInMilliseconds = 500;
        private const int CheckServerSleepTimeoutInMilliseconds = 500;

        private readonly IConfiguration _configuration;
        private readonly ManualResetEvent _stopPlease;
        private Thread _thread;
        private StringBuilder log;

        UIAutomationServiceClient client;
        bool runningTests;

        public AutomationClient(IConfiguration configuration)
        {
            _configuration = configuration;
            _stopPlease = new ManualResetEvent(false);
            log = new StringBuilder();
            client = new UIAutomationServiceClient();
            client.GetTestCaseCompleted += new EventHandler<GetTestCaseCompletedEventArgs>(client_GetTestCaseCompleted);
        }

        public void Dispose()
        {
            Stop();
        }

        public void Start()
        {
            _thread = new Thread(Run);
            _thread.Start();
        }

        public void Stop()
        {
            if (_thread != null)
            {
                _stopPlease.Set();
                _thread.Join();
                _thread = null;
                _stopPlease.Reset();
            }
        }

        private void Run()
        {
            //object uniqueID;
            client.GetTestCaseAsync("5E7661DF-D928-40ff-B747-A4B1957194F9");
            //if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out uniqueID))
            //{
            //    string myString = Convert.ToBase64String((byte[])uniqueID);

            //    client.GetTestCaseAsync(uniqueID as string);
            //}          
        }

        void client_GetTestCaseCompleted(object sender, GetTestCaseCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                // TODO! Log something somehow!
            }
            else
            {
                if (e.Result == null)
                {
                    InvokeTrace("No test case available");
                }
                else
                {
                    ProcessTestCase(e.Result);
                }
            }
        }

        private void ProcessTestCase(TestCaseModel testCase)
        {
            TestCaseResultModel caseResult = new TestCaseResultModel()
            {
                TestPlanID = testCase.TestPlanID,
                TestRunID = testCase.TestRunID,
                TestCaseID = testCase.TestCaseID,
                ActionResults = new System.Collections.ObjectModel.ObservableCollection<ResultBase>(),
                Result = "Pass"
            };

            InvokeTrace(string.Format("Start Processing Test Case: [ID: {0}, Name: {1}]",
              testCase.TestCaseID, testCase.TestCaseName));
            foreach (ActionBaseModel action in testCase.ActionModels)
            {
                if (caseResult.Result == "Pass")
                {
                    InvokeTrace(string.Format("Start Processing Test Action: [Name: {0}, Params: {1}]",
                        action.Name, action.Params));
                    ActionBase actionBase = Activator.CreateInstance(Type.GetType(
                        string.Format("HisoftSmart.Client.AutomationClient.Actions.{0}Action",
                        action.Name)), action.Name, action.Params) as ActionBase;
                    actionBase.ID = action.ID;
                    ProcessTestAction(actionBase);

                    if (actionBase.Result.Result != "Success")
                    {
                        caseResult.Result = "Failed";
                    }

                    caseResult.ActionResults.Add(actionBase.Result);
                }
                else
                {
                    caseResult.ActionResults.Add(new ResultBase()
                    {
                        ActionBaseModel = new ActionBaseModel()
                        {
                            Name = action.Name,
                            ID = action.ID,
                            Params = action.Params,
                        },

                        Result = "Aborted"
                    });
                }
            }

            if (caseResult.Result == "Failed") caseResult.Result = "Failed";

            client.SubmitTestCaseResultAsync(caseResult);
            this.runningTests = false;
        }

        private void ProcessTestAction(ActionBase action)
        {
            if (action == null)
            {
                // TODO - log
                return;
            }

            var mre = new ManualResetEvent(false);
            _configuration.UiDispatcher.BeginInvoke(
                () =>
                {
                    action.Configuration = _configuration;
                    action.AutomationClient = this;
                    action.Do();
                    mre.Set();
                });
            mre.WaitOne();

            Thread.Sleep(GetNextActionTimeoutInMilliseconds);
            return;
        }

        private void InvokeTrace(string msg)
        {
            this.log.AppendLine(msg);
        }
    }
}
